package com.github.butid.data.pipline;

import com.github.butid.data.codec.XmlToCmdMessageDecoder;
import com.github.butid.data.netty.handler.CommandDispacherHandler;
import com.github.butid.data.netty.handler.DesEncrypter;
import com.github.butid.data.netty.handler.HeartbeatHandler;
import com.github.butid.data.netty.springboot.SpringBootNettyProperties;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;

import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

/**
 * TCP服务端Pipline
 * @author wangjing.dc@qq.com
 * @since 2020/8/4
 */
public class JsonTCPServerPipline extends ChannelInitializer<SocketChannel> {

    private final SpringBootNettyProperties properties;

    public JsonTCPServerPipline(SpringBootNettyProperties springBootNettyProperties) {
        this.properties = springBootNettyProperties;
    }

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ch.pipeline()
                // 处理连接超时
                .addLast(new IdleStateHandler(60, 0, 0, TimeUnit.SECONDS))
                .addLast(new HeartbeatHandler())
                // 处理报文长度
//                .addLast(new StringValueLengthFrameDecoder(64* 1024* 1024, 0, 4, 0, 4))

                .addLast(new DelimiterBasedFrameDecoder(
                        64* 1024* 1024, false,
                        Unpooled.copiedBuffer("</root>", Charset.forName("utf-8"))))

                .addLast(new StringDecoder(Charset.forName("utf-8")))
                // 解密
                .addLast(new DesEncrypter())
                // 拆包
                .addLast(new XmlToCmdMessageDecoder())
                .addLast(new StringEncoder(Charset.forName("utf-8")))

                .addLast(new ChannelOutboundHandlerAdapter(){
                    @Override
                    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                        super.write(ctx, msg, promise);
                        // 主动关闭连接
                        if(properties.getAutoClose()){
                            ctx.close();
                        }
                    }
                })

                // 业务转发处理,放到最后一个
                .addLast(new CommandDispacherHandler())

        ;
    }
}
